import operator

import numpy as np
import matplotlib as mpl

import matplotlib.pyplot as plt
mpl.rcParams['axes.unicode_minus'] = False
mpl.rcParams['font.sans-serif'] = 'SimHei'

def file2matrix(filename):
    fr = open(filename)
    arrayOLines = fr.readlines()
    numberOfLines = len(arrayOLines)
    returnMat = np.zeros((numberOfLines, 3))
    classLabelVector = []
    index = 0
    for line in arrayOLines:
        line = line.strip()
        listFromLine = line.split("\t")
        returnMat[index, :3] = listFromLine[:3]
        if listFromLine[-1] == 'didntLike':
            classLabelVector.append(1)
        elif listFromLine[-1] == 'smallDoses':
            classLabelVector.append(2)
        elif listFromLine[-1] == 'largeDoses':
            classLabelVector.append(3)
        index += 1
    return returnMat, classLabelVector


def showDatas(datingDataMat, datingLabels):
    fig, axs = plt.subplots(nrows=2, ncols=2)
    numberOfLabels = len(datingLabels)

    labelColors = []
    for i in datingLabels:
        if i == 1:
            labelColors.append('black')
        if i == 2:
            labelColors.append('orange')
        if i == 3:
            labelColors.append('red')
    # 以样本第一列和第二列画散点图
    axs[0][0].scatter(x=datingDataMat[:, 0], y=datingDataMat[:, 1], color=labelColors, s=15, alpha=0.5)
    # 设置标题
    axs0_title_text = axs[0][0].set_title("每年获得飞行常客里程数与玩视频游戏消耗时间占比")
    axs0_xlabel_text = axs[0][0].set_xlabel("每年获得飞行常客里程数")
    axs0_ylabel_text = axs[0][0].set_ylabel("玩视频游戏消耗时间占比")
    plt.setp(axs0_title_text)
    plt.setp(axs0_xlabel_text)
    plt.setp(axs0_ylabel_text)
    plt.show()


def autoNorm(dataSet):
    # 获得数据的最小值 --min(0) 表示返回的是每一列的最小指 ，min(1)是每一行的最小值
    minVals = dataSet.min(0)
    maxVals = dataSet.max(0)
    ranges = maxVals - minVals
    normDataSet = np.zeros(np.shape(dataSet))
    m = dataSet.shape[0]
    # 对每行归一化
    normDataSet = dataSet - np.tile(minVals, (m, 1))
    normDataSet = normDataSet / np.tile(ranges, (m, 1))
    return normDataSet, ranges, minVals


def classify0(inX, dataSet, labels, k):
    lineCount = len(dataSet)
    dataSet = np.tile(inX, (lineCount, 1)) - dataSet
    dataSet = dataSet ** 2
    # sum(1)行相加
    disTance = dataSet.sum(axis=1)
    disTance = disTance ** 0.5
    sortedDistanceIndex = disTance.argsort()
    classCount = {}
    for i in range(k):
        label = labels[sortedDistanceIndex[i]]
        classCount[label] = classCount.get(label, 0) + 1
    sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True)
    return sortedClassCount[0][0]


def classifyPerson():
    resultList = ['讨厌', '有些喜欢', '非常喜欢']

    precentTats = float(input("玩视频消耗时间比："))
    ffMiles = float(input("每年获得飞行常客里程数："))
    iceCream = float(input("每周消费冰淇淋公升数："))

    filename = 'datingTestSet.txt'

    datingDataMat, datingLabels = file2matrix(filename)

    normMat, ranges, minVals = autoNorm(datingDataMat)

    inArr = np.array([precentTats, ffMiles, iceCream])

    normInArr = (inArr - minVals) / ranges

    classifyResult = classify0(normInArr, normMat, datingLabels, 3)


def datingClassTest():
    filename = 'datingTestSet.txt'
    datingDataMat, datingLabels = file2matrix(filename)
    hoRatio = 0.1
    normMat, ranges, minVals = autoNorm(datingDataMat)
    m = normMat.shape[0]
    numTestVecs = int(m * hoRatio)
    errCount = 0.0

    for i in range(numTestVecs):
        classifyResult = classify0(normMat[i, :],
                                   normMat[numTestVecs:m, :],
                                   datingLabels[numTestVecs:m], 4)
        print("分类结果：%d\t 真实类别：%d" % (classifyResult,datingLabels[i]))
        if classifyResult != datingLabels[i]:
            errCount += 1
    print("错误率：%f" % (errCount / float(numTestVecs)) * 100)


if __name__ == "__main__":
    filename = "datingTestSet.txt"
    # 打开并处理数据
    datingDataMat, datingLabels = file2matrix(filename)
    showDatas(datingDataMat, datingLabels)

    # 2、测试代码
    datingClassTest()

